#include <iostream>
#include <cassert>
#include <unistd.h>
#include <vector>

#define MAKERAND() srand((unsigned long)time(0) ^ rand() ^ getpid())
#define Max_Process 5
// 定义一个无参返回值为void的函数指针
typedef void (*func_t)();
using namespace std;

// 要执行的任务
void download_task()
{
    cout << "正在下载 " << endl;
    sleep(1);
}
void open_task()
{
    cout << "正在打开 " << endl;
    sleep(1);
}
void close_task()
{
    cout << "正在关闭 " << endl;
    sleep(1);
}
void LoadTask(vector<func_t> &taskPool)
{
    taskPool.push_back(download_task);
    taskPool.push_back(open_task);
    taskPool.push_back(close_task);
}

class Process
{
public:
    Process(pid_t ProcessId, int WriteFd)
        : ProcessId_(ProcessId), WriteFd_(WriteFd), ProcessName_("ProcessNum:" + to_string(ProcessNum_) + " | pid:" + to_string(ProcessId_) + " | fd:" + to_string(WriteFd_))
    {
        ++ProcessNum_;
    }

public:
    static int ProcessNum_; // 对应进程的编号
    string ProcessName_;    // 子进程的名称
    pid_t ProcessId_;       // 子进程的pid
    int WriteFd_;           // 子进程管道的写端
};
int Process::ProcessNum_ = 0;

void SendTask(const Process &pro, int TaskNum)
{
    cout << "send to process: " << pro.ProcessName_ << endl;
    cout << "do task num: " << TaskNum << endl;
    int n=write(pro.WriteFd_,&TaskNum,sizeof(TaskNum));
    assert(n==sizeof(TaskNum));
}

int recvTask(int ReadFd){
    int code;  //code是读到的任务
    int n=read(ReadFd,&code,sizeof(code));  //将读取的TaskNum存入code中
    assert(n==sizeof(code));
    return code;
}

void createProcessPool(vector<Process> &ProcessPool,vector<func_t>& TaskPool)
{
    for (int i = 0; i < Max_Process; i++)
    {
        // 创建管道,建立父进程与相应子进程的读端与写端
        int pipefd[2];
        int n = pipe(pipefd);
        assert(n == 0);

        // fork出子进程
        pid_t id = fork();
        assert(id >= 0);
        if (id == 0)
        {
            // 关闭子进程的写端
            close(pipefd[1]);
            while(1)
            {
            // 子进程读取
            int commandCode=recvTask(pipefd[0]);
            if(commandCode>=0&&commandCode<=TaskPool.size()){
                TaskPool[commandCode]();
            }
            else{
                cout<<"Process receive code error"<<endl;
            }
            }
            exit(0);
        }

        // 父进程关闭与对应子程序的读端，并将创建的线程推入线程池中
        close(pipefd[0]);
        Process pro(id, pipefd[1]);
        ProcessPool.push_back(pro);
    }
}

// 父进程写，创建五个子进程让特定的进程读取特定的内容
int main()
{
    MAKERAND();
    vector<func_t> TaskPool;
    LoadTask(TaskPool);
    vector<Process> ProcessPool;
    createProcessPool(ProcessPool,TaskPool);

    // 父进程控制子进程
    int ProcessNum = ProcessPool.size();
    int TaskNum = TaskPool.size();
    while (1)
    {
        // 1、随机选择一个子进程，即随机生成一个进程下标
        int ProcessIndex = rand() % ProcessNum;
        // 2、随机选择一个任务
        int TaskIndex = rand() % TaskNum;
        // 发送给相应的子进程并读取
        SendTask(ProcessPool[ProcessIndex], TaskIndex);
        sleep(1);
    }
}